using System.Collections.Generic;
using FireStarter.Base;
using FireStarter.CodeGeneration;
using FireStarterModeller.BO;
using Habanero.BO;
using Habanero.BO.ClassDefinition;
using Habanero.BO.Loaders;
using NUnit.Framework;

namespace FireStarter.Test.CodeGeneration
{
    [TestFixture]
    public class TestUtilities
    {
        [TestFixtureSetUp]
        public void TestFixtureSetUp()
        {
            ClassDef.ClassDefs.Clear();
            ClassDef.ClassDefs.Add(new XmlClassDefsLoader(BOBroker.GetClassDefsXml(), new DtdLoader()).LoadClassDefs());
        }

        [SetUp]
        public void SetUp()
        {
            BORegistry.DataAccessor = new DataAccessorInMemory();
        }

        [Test]
        public void TestStringIsWrappedInQuotes()
        {
            //---------------Set up test pack-------------------
            //---------------Execute Test ----------------------
            //---------------Test Result -----------------------
            Assert.IsFalse(Utilities.StringIsWrappedInQuotes(null));
            Assert.IsFalse(Utilities.StringIsWrappedInQuotes(""));
            Assert.IsFalse(Utilities.StringIsWrappedInQuotes(@""""));
            Assert.IsFalse(Utilities.StringIsWrappedInQuotes(@"""hello"));
            Assert.IsFalse(Utilities.StringIsWrappedInQuotes(@"""hello""world"));
            Assert.IsTrue(Utilities.StringIsWrappedInQuotes(@"""hello"""));
            Assert.IsTrue(Utilities.StringIsWrappedInQuotes(@""""""));
        }

        [Test]
        public void TestStringHasOnlyWhitespaceSinceLastNewline()
        {
            //---------------Set up test pack-------------------
            //---------------Execute Test ----------------------
            //---------------Test Result -----------------------
            Assert.IsFalse(Utilities.StringHasOnlyWhitespaceSinceLastNewline(""));
            Assert.IsFalse(Utilities.StringHasOnlyWhitespaceSinceLastNewline("asdf"));
            Assert.IsFalse(Utilities.StringHasOnlyWhitespaceSinceLastNewline("\t\t"));
            Assert.IsFalse(Utilities.StringHasOnlyWhitespaceSinceLastNewline("  "));
            Assert.IsTrue(Utilities.StringHasOnlyWhitespaceSinceLastNewline("\r\n"));
            Assert.IsTrue(Utilities.StringHasOnlyWhitespaceSinceLastNewline("\r\n  "));
            Assert.IsTrue(Utilities.StringHasOnlyWhitespaceSinceLastNewline("\r\n\t\t"));
            Assert.IsTrue(Utilities.StringHasOnlyWhitespaceSinceLastNewline("\r\n  \t\t  "));
            Assert.IsTrue(Utilities.StringHasOnlyWhitespaceSinceLastNewline("\r\n\r\n"));
            Assert.IsFalse(Utilities.StringHasOnlyWhitespaceSinceLastNewline("\r\n11"));
            Assert.IsFalse(Utilities.StringHasOnlyWhitespaceSinceLastNewline("\r\n 11"));
            Assert.IsFalse(Utilities.StringHasOnlyWhitespaceSinceLastNewline("\r\n\t11"));
            Assert.IsFalse(Utilities.StringHasOnlyWhitespaceSinceLastNewline("\r\n11   "));
            Assert.IsFalse(Utilities.StringHasOnlyWhitespaceSinceLastNewline("\r\n\r\n11"));
            Assert.IsTrue(Utilities.StringHasOnlyWhitespaceSinceLastNewline("\r\n11\r\n"));
        }

        [Test]
        public void TestGetRelativePath()
        {
            //---------------Set up test pack-------------------
            const string absolutePath = "C:\\Temp";
            const string relativeTo = "C:\\";

            //---------------Execute Test ----------------------
            string path = Utilities.GetRelativePath(absolutePath, relativeTo);

            //---------------Test Result -----------------------
            Assert.AreEqual("Temp", path);
        }

        [Test]
        public void TestGetRelativePath_File()
        {
            //---------------Set up test pack-------------------
            const string absolutePath = "C:\\Temp.txt";
            const string relativeTo = "C:\\";

            //---------------Execute Test ----------------------
            string path = Utilities.GetRelativePath(absolutePath, relativeTo);

            //---------------Test Result -----------------------
            Assert.AreEqual("Temp.txt", path);
        }

        [Test]
        public void TestGetRelativePath_Reverse()
        {
            //---------------Set up test pack-------------------
            const string absolutePath = "C:\\";
            const string relativeTo = "C:\\Temp";

            //---------------Execute Test ----------------------
            string path = Utilities.GetRelativePath(absolutePath, relativeTo);

            //---------------Test Result -----------------------
            Assert.AreEqual("..\\", path);
        }

        [Test]
        public void TestGetRelativePath_Advanced()
        {
            //---------------Set up test pack-------------------
            const string absolutePath = "C:\\Temp\\MyFolder\\MySubFolder";
            const string relativeTo = "C:\\Temp2";

            //---------------Execute Test ----------------------
            string path = Utilities.GetRelativePath(absolutePath, relativeTo);

            //---------------Test Result -----------------------
            Assert.AreEqual("..\\Temp\\MyFolder\\MySubFolder", path);
        }


        [Test]
        public void Test_OrderedClassesForDeletion_ReorderParentChild()
        {
            //---------------Set up test pack-------------------

            DMClass parentClass = (DMClass)TestUtilsCodeGen.CreateModelClass("ParentClass");
            parentClass.Assembly=new DMAssembly(TestUtilsCodeGen.GetRandomString());
            DMClass childClass = (DMClass)TestUtilsCodeGen.CreateModelClass("ChildClass");
            childClass.Assembly= new DMAssembly(TestUtilsCodeGen.GetRandomString());

            DMRelationship parentToChildRelationship = new DMRelationship();
            parentToChildRelationship.Cardinality = Cardinality.Multiple;
            parentToChildRelationship.RelatedClass = childClass;
            parentClass.OwnerRelationships.Add(parentToChildRelationship);

            List<IModelClass> modelClasses = new List<IModelClass> { parentClass, childClass };
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            IList<IModelElement> modelClassesOutput = Utilities.OrderModelClassesForDeletion(modelClasses);
            //---------------Test Result -----------------------
            Assert.AreEqual(2, modelClassesOutput.Count);
            Assert.AreSame(childClass, modelClassesOutput[0]);
            Assert.AreSame(parentClass, modelClassesOutput[1]);
        }

        [Test]
        public void Test_OrderedClassesForDeletion_NoChange()
        {
            //---------------Set up test pack-------------------
            IModelClass parentClass = TestUtilsCodeGen.CreateModelClass("ParentClass");
            DMClass childClass = TestUtilsCodeGen.CreateModelClass("ChildClass");

            DMRelationship parentToChildRelationship = new DMRelationship();
            parentToChildRelationship.Cardinality = Cardinality.Single;
            parentToChildRelationship.RelatedClass = childClass;
            parentClass.Relationships.Add(parentToChildRelationship);

            List<IModelClass> modelClasses = new List<IModelClass> { parentClass, childClass };
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            IList<IModelElement> modelClassesOutput = Utilities.OrderModelClassesForDeletion(modelClasses);
            //---------------Test Result -----------------------
            Assert.AreEqual(2, modelClassesOutput.Count);
            Assert.AreSame(parentClass, modelClassesOutput[0]);
            Assert.AreSame(childClass, modelClassesOutput[1]);
        }

        [Test]
        public void Test_OrderedClassesForDeletion_Complex()
        {
            //---------------Set up test pack-------------------
            List<DMClass> expectedModelClasses;
            List<DMClass> modelClasses = TestUtilsCodeGen.GetParentChildHeirarchy(out expectedModelClasses);
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            IList<IModelClass> modelClassesCopy = new List<IModelClass>();
            foreach (DMClass dmClass in modelClasses)
            {
                modelClassesCopy.Add(dmClass);
            }
            IList<IModelElement> modelClassesOutput = Utilities.OrderModelClassesForDeletion(modelClassesCopy);
            //---------------Test Result -----------------------
            Assert.AreEqual(expectedModelClasses.Count, modelClassesOutput.Count);
            for (int position = 0; position < expectedModelClasses.Count; position++)
            {
                Assert.AreSame(expectedModelClasses[position], modelClassesOutput[position]);
            }
        }
    }
}
